Passed
Push — master ( e6b8b3...300be1 )
by Dev
01:32
created

helpers.js ➔ convertShortchutForLink   A

Complexity

Conditions 4

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 8
dl 0
loc 12
rs 10
c 0
b 0
f 0
1
/**
2
 * List of all functions
3
 *
4
 * - liveBlock(attr)
5
 * - liveForm(attr)
6
 *
7
 * -  seasonedBackground
8
 * - responsiveImage(string)    Relative to Liip filters
9
 * - uncloakLinks(attr)
10
 * - convertFormFromRot13(attr)
11
 * - readableEmail(attr)
12
 * - convertImageLinkToWebPLink()
13
 */
14
15
/**
16
 * Live Block Watcher (and button)
17
 *
18
 * Fetch (ajax) function permitting to get block via a POST request
19
 *
20
 * @param {string} attribute
21
 */
22
export function liveBlock(
23
  liveBlockAttribute = 'data-live',
24
  liveFormSelector = '.live-form'
25
) {
26
  var btnToBlock = function (event, btn) {
27
    btn.setAttribute(
28
      liveBlockAttribute,
29
      btn.getAttribute('src-' + liveBlockAttribute)
30
    );
31
    getLiveBlock(btn);
32
  };
33
34
  var getLiveBlock = function (item) {
35
    fetch(item.getAttribute(liveBlockAttribute), {
36
      //headers: { "Content-Type": "application/json", Accept: "text/plain" },
37
      method: 'POST',
38
      credentials: 'include',
39
    })
40
      .then(function (response) {
41
        return response.text();
42
      })
43
      .then(function (body) {
44
        item.removeAttribute(liveBlockAttribute);
45
        item.outerHTML = body;
46
      })
47
      .then(function () {
48
        document.dispatchEvent(new Event('DOMChanged'));
0 ignored issues
show
Bug introduced by
The variable Event seems to be never declared. If this is a global, consider adding a /** global: Event */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
49
      });
50
  };
51
52
  var htmlLoader =
53
    '<div style="width:1em;height:1em;border: 2px solid #222;border-top-color: #fff;border-radius: 50%;  animation: 1s spin linear infinite;"></div><style>@keyframes spin {from{transform:rotate(0deg)}to{transform:rotate(360deg)}}</style>';
54
55
  var setLoader = function (form) {
56
    var $submitButton = getSubmitButton(form);
57
    if ($submitButton !== undefined) {
58
      var initialButton = $submitButton.outerHTML;
0 ignored issues
show
Unused Code introduced by
The variable initialButton seems to be never used. Consider removing it.
Loading history...
59
      $submitButton.innerHTML = '';
60
      $submitButton.outerHTML = htmlLoader;
61
    }
62
  };
63
64
  var sendForm = function (form, liveFormBlock) {
65
    setLoader(form);
66
67
    var formData = new FormData(form.srcElement);
68
    fetch(form.srcElement.action, {
69
      method: 'POST',
70
      body: formData,
71
      credentials: 'include',
72
    })
73
      .then(function (response) {
74
        return response.text();
75
      })
76
      .then(function (body) {
77
        liveFormBlock.outerHTML = body;
78
      })
79
      .then(function () {
80
        document.dispatchEvent(new Event('DOMChanged'));
0 ignored issues
show
Bug introduced by
The variable Event seems to be never declared. If this is a global, consider adding a /** global: Event */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
81
      });
82
  };
83
84
  var getSubmitButton = function (form) {
85
    if (form.srcElement.querySelector('[type=submit]') !== null) {
86
      return form.srcElement.querySelector('[type=submit]');
87
    }
88
    if (form.srcElement.getElementsByTagName('button') !== null) {
89
      return form.srcElement.getElementsByTagName('button')[0];
90
    }
91
    return null;
92
  };
93
94
  // Listen data-live
95
  document.querySelectorAll('[' + liveBlockAttribute + ']').forEach((item) => {
96
    getLiveBlock(item);
97
  });
98
99
  // Listen button src-data-live
100
  document
101
    .querySelectorAll('[src-' + liveBlockAttribute + ']')
102
    .forEach((item) => {
103
      item.addEventListener('click', (event) => {
104
        btnToBlock(event, item);
105
      });
106
    });
107
108
  // Listen live-form
109
  document.querySelectorAll(liveFormSelector).forEach((item) => {
110
    if (item.querySelector('form') !== null) {
111
      item.querySelector('form').addEventListener('submit', (e) => {
112
        e.preventDefault();
113
        sendForm(e, item);
114
      });
115
    }
116
  });
117
}
118
119
/**
120
 *
121
 *
122
 */
123
export function seasonedBackground() {
124
  document.querySelectorAll('[x-hash]').forEach(function (element) {
125
    if (window.location.hash) {
126
      if (element.getAttribute('x-hash') == window.location.hash.substring(1)) {
127
        element.parentNode.parentNode.parentNode
128
          .querySelectorAll('img')
129
          .forEach(function (img) {
130
            img.style = 'display:none';
131
          });
132
        element.style = 'display:block';
133
        console.log('change element');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
134
      }
135
    }
136
  });
137
}
138
139
/**
140
 * Transform image's path (src) produce with Liip to responsive path
141
 *
142
 * @param {string} src
143
 */
144
export function responsiveImage(src) {
145
  var screenWidth = window.innerWidth;
146
  if (screenWidth <= 576) {
147
    src = src.replace('/default/', '/xs/');
148
  } else if (screenWidth <= 768) {
149
    src = src.replace('/default/', '/sm/');
150
  } else if (screenWidth <= 992) {
151
    src = src.replace('/default/', '/md/');
152
  } else if (screenWidth <= 1200) {
153
    src = src.replace('/default/', '/lg/');
154
  } else {
155
    // 1200+
156
    src = src.replace('/default/', '/xl/');
157
  }
158
159
  return src;
160
}
161
162
/**
163
 * Convert elements wich contain attribute (data-href) in normal link (a href)
164
 * You can use a callback function to decrypt the link (eg: rot13ToText ;-))
165
 *
166
 * @param {string}  attribute
167
 */
168
export async function uncloakLinks(attribute = 'data-rot') {
169
  var convertLink = function (element) {
170
    // fix "bug" with img
171
    if (element.getAttribute(attribute) === null) {
172
      var element = element.closest('[' + attribute + ']');
173
    }
174
    if (element.getAttribute(attribute) === null) return;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
175
    var link = document.createElement('a');
176
    var href = element.getAttribute(attribute);
177
    element.removeAttribute(attribute);
178
    for (var i = 0, n = element.attributes.length; i < n; i++) {
179
      link.setAttribute(
180
        element.attributes[i].nodeName,
181
        element.attributes[i].nodeValue
182
      );
183
    }
184
    link.innerHTML = element.innerHTML;
185
    link.setAttribute(
186
      'href',
187
      responsiveImage(convertShortchutForLink(rot13ToText(href)))
188
    );
189
    element.parentNode.replaceChild(link, element);
190
    return link;
191
  };
192
193
  var convertThemAll = function (attribute) {
194
    [].forEach.call(document.querySelectorAll('[' + attribute + ']'), function (
195
      element
196
    ) {
197
      convertLink(element);
198
    });
199
  };
200
201
  var fireEventLinksBuilt = async function (element, event) {
202
    await document.dispatchEvent(new Event('DOMChanged'));
0 ignored issues
show
Bug introduced by
The variable Event seems to be never declared. If this is a global, consider adding a /** global: Event */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
203
204
    var clickEvent = new Event(event.type);
205
    element.dispatchEvent(clickEvent);
206
  };
207
208
  var convertLinkOnEvent = async function (event) {
209
    // convert them all if it's an image (thanks this bug), permit to use gallery (baguetteBox)
210
    if (event.target.tagName == 'IMG') {
211
      await convertThemAll(attribute);
212
      var element = event.target;
213
    } else {
214
      var element = convertLink(event.target);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable element already seems to be declared on line 212. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
215
    }
216
    fireEventLinksBuilt(element, event);
217
  };
218
219
  [].forEach.call(document.querySelectorAll('[' + attribute + ']'), function (
220
    element
221
  ) {
222
    element.addEventListener(
223
      'touchstart',
224
      function (e) {
225
        convertLinkOnEvent(e);
226
      },
227
      { once: true, passive: true }
228
    );
229
    element.addEventListener(
230
      'click',
231
      function (e) {
232
        convertLinkOnEvent(e);
233
      },
234
      { once: true }
235
    );
236
    element.addEventListener(
237
      'mouseover',
238
      function (e) {
239
        convertLinkOnEvent(e);
240
      },
241
      { once: true }
242
    );
243
  });
244
}
245
246
/**
247
 * Convert action attr encoded in rot 13 to normal action with default attr `data-frot`
248
 *
249
 * @param {string}  attribute
250
 */
251
export function convertFormFromRot13(attribute = 'data-frot') {
252
  [].forEach.call(document.querySelectorAll('[' + attribute + ']'), function (
253
    element
254
  ) {
255
    var action = element.getAttribute(attribute);
256
    element.removeAttribute(attribute);
257
    element.setAttribute(
258
      'action',
259
      convertShortchutForLink(rot13ToText(action))
260
    );
261
  });
262
}
263
264
export function convertShortchutForLink(str) {
265
  if (str.charAt(0) == '-') {
266
    return str.replace('-', 'http://');
267
  }
268
  if (str.charAt(0) == '_') {
269
    return str.replace('_', 'https://');
270
  }
271
  if (str.charAt(0) == '@') {
272
    return str.replace('@', 'mailto:');
273
  }
274
  return str;
275
}
276
277
/**
278
 * readableEmail(selector) Transform an email encoded with rot13 in a readable mail (and add mailto:)
279
 *
280
 * @param {string}  text
281
 */
282
export function readableEmail(selector) {
283
  document.querySelectorAll(selector).forEach(function (item) {
284
    var mail = rot13ToText(item.textContent);
285
    item.innerHTML = '<a href="mailto:' + mail + '">' + mail + '</a>';
286
    if (selector.charAt(0) == '.') {
287
      item.classList.remove(selector.substring(1));
288
    }
289
  });
290
}
291
292
/**
293
 * Decode rot13
294
 *
295
 * @param {string}  str
296
 */
297
export function rot13ToText(str) {
298
  return str.replace(/[a-zA-Z]/g, function (c) {
299
    return String.fromCharCode(
300
      (c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26
301
    );
302
  });
303
}
304
305
export function testWebPSupport() {
306
  var elem = document.createElement('canvas');
307
308
  if (elem.getContext && elem.getContext('2d')) {
309
    return elem.toDataURL('image/webp').indexOf('data:image/webp') == 0;
0 ignored issues
show
Best Practice introduced by
Comparing elem.toDataURL("image/we...exOf("data:image/webp") to 0 using the == operator is not safe. Consider using === instead.
Loading history...
310
  }
311
312
  return false;
313
}
314
315
/**
316
 * Used in ThemeComponent
317
 */
318
export function convertImageLinkToWebPLink() {
319
  var switchToWebP = function () {
320
    [].forEach.call(document.querySelectorAll('a[dwl]'), function (element) {
321
      var href = responsiveImage(element.getAttribute('dwl'));
322
      element.setAttribute('href', href);
323
      element.removeAttribute('dwl');
324
    });
325
  };
326
327
  if (testWebPSupport()) switchToWebP();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
328
}
329
330
/**
331
 * Simple Image Lazy Loader
332
 * original from : https://davidwalsh.name/lazyload-image-fade
333
 *
334
 * @param {string}  attribute
335
 *
336
 * @example
337
 * imgLazyLoad()
338
 * <span data-img=/img/me.png>Tagada</span> or <img data-img=/img/me.png alt=Tagada>
339
 *
340
 * will be converted to
341
 *
342
 * <img src=/img/me.png alt=Tagada />
343
 *
344
 * still used in piedvert. To remove ?!
345
 */
346
export function imgLazyLoad(attribute = 'data-img') {
347
  [].forEach.call(document.querySelectorAll('[' + attribute + ']'), function (
348
    img
349
  ) {
350
    var newDomImg = document.createElement('img');
351
    var src = img.getAttribute(attribute);
352
    img.removeAttribute(attribute);
353
    for (var i = 0, n = img.attributes.length; i < n; i++) {
354
      newDomImg.setAttribute(
355
        img.attributes[i].nodeName,
356
        img.attributes[i].nodeValue
357
      );
358
    }
359
    if (newDomImg.getAttribute('alt') === null && img.textContent != '') {
360
      newDomImg.setAttribute('alt', img.textContent);
361
    }
362
    newDomImg.setAttribute(
363
      'src',
364
      typeof responsiveImage === 'function' ? responsiveImage(src) : src
365
    );
366
    img.outerHTML = newDomImg.outerHTML;
367
  });
368
}
369